home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 3 / Cream of the Crop 3.iso / program / asmtext1.zip / 87.SET < prev    next >
Text File  |  1994-02-27  |  15KB  |  323 lines

  1. References to the various Central Processing Units (CPUs) as the "86"
  2. refers to either the 8088, 8086, 80186, 80286, etc.  References to
  3. the various coprocessors as the "87" refers to either the 8087, the 287,
  4. the 387, or the special IIT-2C87 processor.
  5.  
  6. The 8087 and 287 Coprocessors
  7.  
  8. All IBM-PC's, and most clones, contain a socket for a floating
  9. point coprocessor.  If you shell out between $80 and $300, and
  10. plug the appropriate chip into that socket, then a host of
  11. floating point instructions is added to the assembly language
  12. instruction set.
  13.  
  14. The original IBM-PC, and the XT, accept the original floating
  15. point chip, the 8087.  The AT accepts a later update, the 287.
  16. From a programming standpoint, the two chips are nearly
  17. identical: the 287 adds the instructions FSETPM and FSTSW AX, and
  18. ignores the instructions FENI and FDISI.  There is, however, a
  19. rather nasty design flaw in the 8087, that was corrected in the
  20. 287.
  21.  
  22. To understand the flaw, you must understand how the 86 and 87
  23. work as coprocessors. Whenever the 86 sees a floating point
  24. instruction, it communicates the instruction, and any associated
  25. memory operands, to the 87.  Then the 86 goes on to its next
  26. instruction, operating in parallel with the 87.  That's OK, so
  27. long as the following instructions don't do one of the following:
  28.  
  29.   1. Execute another floating point instruction; or
  30.  
  31.   2. Try to read the results of the still-executing floating
  32.      point instruction.
  33.  
  34. If they do, then you must provide an instruction called WAIT (or
  35. synonymously FWAIT), which halts the 86 until the 87 is finished.
  36. For almost all floating point instructions, it should not be
  37. necessary to provide an explicit FWAIT; the 86 ought to know that
  38. it should wait.  For the 8087, it IS necessary to give an
  39. explicit FWAIT before each floating point instruction: that is
  40. the flaw.
  41.  
  42. Because of the flaw, all assemblers supporting the 8087 will
  43. silently insert an FWAIT code (hex 9B) before all 87
  44. instructions, except those few (the FN instructions other than
  45. FNOP) not requiring the FWAIT.  
  46.  
  47. * Microsoft recognizes the new 287 instructions, if and only if
  48.   it sees the .287 directive. In general, don't attempt to police
  49.   your instruction usage-- if you use an instruction available on a
  50.   limited number of processors, I trust that you are programming
  51.   for one of those processors.
  52.  
  53. In summary, if your program will be running only on machines with
  54. a 287, you can give ".287" directive. Your programs will be
  55. significantly shorter than if they were assembled by Microsoft.
  56. If you want your programs to run on all machines containing a
  57. floating point chip, you should refrain from specifying .287.
  58.  
  59. WARNING: The most common mistake 87 programmers make is to try to
  60. read the results of an 87 operation in 86 memory, before the
  61. results are ready.  At least on my AT, the system often crashes
  62. when you do this!  If your program runs correctly when single
  63. stepped, but crashes when set loose, then chances are you need an
  64. extra explicit FWAIT somewhere.
  65.  
  66.  
  67. Emulating the 8087 by Software
  68.  
  69. There is a software package provided with many compilers
  70. (Borland's Turbo C and most Microsoft compilers, for example)
  71. that emulates the 8087 instruction set.  The emulator is very
  72. cleverly implemented so that the programmer need not know whether
  73. a floating point chip will be available, or whether emulation
  74. will be necessary.  This is done by having the linker replace all
  75. floating point machine instructions with INT calls to certain
  76. interrupts, dedicated to emulation.  The interrupt handlers
  77. interpret the operands to the instructions, and emulate the 8087.
  78.  
  79. The Floating Point Stack
  80.  
  81. The 87 has its own register set, of 8 floating point numbers
  82. occupying 10 bytes each, plus 14 bytes of status and control
  83. information.  Many of the 87's instructions cause the numbers to
  84. act like a stack, much like a Hewlett-Packard calculator.  For
  85. this reason, the numbers are called the floating point stack.
  86.  
  87. The standard name for the top element of the floating point stack
  88. is either ST or ST(0); the others are named ST(1) through ST(7).
  89. Thus, for example, the instruction to add stack element number 3
  90. into the top stack element is usually coded FADD ST,ST(3).
  91.  
  92.  
  93. Floating Point Initializations
  94.  
  95. In general, you use the 87 by loading numbers from 86 memory to
  96. the 87 stack (using FLD instructions), calculating on the 87
  97. stack, and storing the results back to 86 memory (using FST and
  98. FSTP instructions).  There are seven constant numbers built into
  99. the 87 instruction set: zero, one, Pi, and four logarithmic
  100. conversion constants.  These can be loaded using the FLD0, FLD1,
  101. FLDPI, FLDL2T, FLDL2E, FLDLG2, and FLDLN2 instructions.  All
  102. other constants must be declared in, then loaded from, 86 memory.
  103. Integer constant words and doublewords can be loaded via FILD.
  104. Non-integer constant doubleword, quadwords, and ten-byte numbers
  105. can be loaded via FLD.
  106.  
  107.  
  108. Floating Point Operand Types
  109.  
  110. The list of floating point instructions contains a variety of
  111. operand types.  Here is a brief explanation of those types:
  112.  
  113. 0        stands for the top element of the floating point stack.
  114.          A synonym for 0 is ST or ST(0).
  115.  
  116. i        stands for element number i of the floating point stack.
  117.          i can range from 0 through 7.  A synonym for i is ST(i).
  118.  
  119. mem10r   is a 10-byte memory quantity (typically declared with a
  120.          DT directive) containing a full precision floating point
  121.          number. Intel recommends that you NOT store your numbers
  122.          in full precision; that you use the following double
  123.          precision format instead.  Full precision numbers are
  124.          intended for storage of intermediate results (on the
  125.          stack); they exist to insure maximum accuracy for
  126.          calculations on double precision numbers, which is the
  127.          official external format of 87 numbers.
  128.  
  129. mem8r    is an 8-byte memory quantity (typically declared with a
  130.          DQ directive) containing a double precision floating
  131.          point number.  This is the best format for floating
  132.          point numbers on the 87.  The 87 takes the same amount
  133.          of time on double precision calculations as it does on
  134.          single precision.  The only extra time is the memory
  135.          access of 4 more bytes; negligible in comparison to the
  136.          calculation time.
  137.  
  138. mem4r    is a 4-byte quantity (typically defined with a DD
  139.          directive) containing a single precision floating point
  140.          number.
  141.  
  142. mem10d   is a 10-byte quantity (also defined via DT) containing a
  143.          special Binary Coded Decimal format recognized by the
  144.          FBLD and FBSTP instructions.  This format is useful for
  145.          input and output of floating point numbers.
  146.  
  147. mem4i    is a 4-byte quantity representing a signed integer in
  148.          two's-complement notation.
  149.  
  150. mem2i    is a 2-byte quantity representing a signed integer in
  151.          two's-complement notation.
  152.  
  153. mem14    and mem94 are 14- and 94-byte buffers containing the 87
  154.          machine state.
  155.  
  156. The 87 Instruction Set
  157.  
  158. Following is the 87 instruction set.  The "w" in the opcode field
  159. is the FWAIT opcode, hex 9B, which is suppressed if .287 is
  160. selected.  Again, "0", "1", and "i" stand for the associated
  161. floating point stack registers, not constant numbers!  Constant
  162. numbers in the descriptions are given with decimal points: 0.0,
  163. 1.0, 2.0, 10.0.
  164.  
  165.  
  166.     Opcode    Instruction     Description
  167.  
  168.  w  D9 F0     F2XM1           0 := (2.0 ** 0) - 1.0
  169.  w  DB F1     F4X4            IIT only: 4 by 4 matrix multiply
  170.  w  D9 E1     FABS            0 := |0|
  171.  w  DE C1     FADD            1 := 1 + 0, pop
  172.  w  D8 C0+i   FADD i          0 := i + 0
  173.  w  DC C0+i   FADD i,0        i := i + 0
  174.  w  D8 C0+i   FADD 0,i        0 := i + 0
  175.  w  D8 /0     FADD mem4r      0 := 0 + mem4r
  176.  w  DC /0     FADD mem8r      0 := 0 + mem8r
  177.  w  DE C0+i   FADDP i,0       i := i + 0, pop
  178.  w  DB E8     FBANK 0         IIT only: set bank pointer to default
  179.  w  DB EB     FBANK 1         IIT only: set bank pointer to bank 1
  180.  w  DB EA     FBANK 2         IIT only: set bank pointer to bank 2
  181.  w  DF /4     FBLD mem10d     push, 0 := mem10d
  182.  w  DF /6     FBSTP mem10d    mem10d := 0, pop
  183.  w  D9 E0     FCHS            0 := -0
  184. 9B  DB E2     FCLEX           clear exceptions
  185.  w  D8 D1     FCOM            compare 0 - 1
  186.  w  D8 D0+i   FCOM 0,i        compare 0 - i
  187.  w  D8 D0+i   FCOM i          compare 0 - i
  188.  w  D8 /2     FCOM mem4r      compare 0 - mem4r
  189.  w  DC /2     FCOM mem8r      compare 0 - mem8r
  190.  w  D8 D9     FCOMP           compare 0 - 1, pop
  191.  w  D8 D8+i   FCOMP 0,i       compare 0 - i, pop
  192.  w  D8 D8+i   FCOMP i         compare 0 - i, pop
  193.  w  D8 /3     FCOMP mem4r     compare 0 - mem4r, pop
  194.  w  DC /3     FCOMP mem8r     compare 0 - mem8r, pop
  195.  w  DE D9     FCOMPP          compare 0 - 1, pop both
  196.  w  D9 FF     FCOS            387 only: push, 1/0 := cosine(old 0)
  197.  w  D9 F6     FDECSTP         decrement stack pointer
  198.  w  DB E1     FDISI           disable interrupts (.287 ignore)
  199.  w  DE F9     FDIV            1 := 1 / 0, pop
  200.  w  D8 F0+i   FDIV i          0 := 0 / i
  201.  w  DC F8+i   FDIV i,0        i := i / 0
  202.  w  D8 F0+i   FDIV 0,i        0 := 0 / i
  203.  w  D8 /6     FDIV mem4r      0 := 0 / mem4r
  204.  w  DC /6     FDIV mem8r      0 := 0 / mem8r
  205.  w  DE F8+i   FDIVP i,0       i := i / 0, pop
  206.  w  DE F1     FDIVR           1 := 0 / 1, pop
  207.  w  D8 F8+i   FDIVR i         0 := i / 0
  208.  w  DC F0+i   FDIVR i,0       i := 0 / i
  209.  w  D8 F8+i   FDIVR 0,i       0 := i / 0
  210.  w  D8 /7     FDIVR mem4r     0 := mem4r / 0
  211.  w  DC /7     FDIVR mem8r     0 := mem8r / 0
  212.  w  DE F0+i   FDIVRP i,0      i := 0 / i, pop
  213.  w  DB E0     FENI            enable interrupts (.287 ignore)
  214.  w  DD C0+i   FFREE i         empty i
  215.  w  DE /0     FIADD mem2i     0 := 0 + mem4i
  216.  w  DA /0     FIADD mem4i     0 := 0 + mem2i
  217.  w  DE /2     FICOM mem2i     compare 0 - mem2i
  218.  w  DA /2     FICOM mem4i     compare 0 - mem4i
  219.  w  DE /3     FICOMP mem2i    compare 0 - mem2i, pop
  220.  w  DA /3     FICOMP mem4i    compare 0 - mem4i, pop
  221.  w  DE /6     FIDIV mem2i     0 := 0 / mem2i
  222.  w  DA /6     FIDIV mem4i     0 := 0 / mem4i
  223.  w  DE /7     FIDIVR mem2i    0 := mem2i / 0
  224.  w  DA /7     FIDIVR mem4i    0 := mem4i / 0
  225.  w  DF /0     FILD mem2i      push, 0 := mem2i
  226.  w  DB /0     FILD mem4i      push, 0 := mem4i
  227.  w  DF /5     FILD mem8i      push, 0 := mem8i
  228.  w  DE /1     FIMUL mem2i     0 := 0 * mem2i
  229.  w  DA /1     FIMUL mem4i     0 := 0 * mem4i
  230.  w  D9 F7     FINCSTP         increment stack pointer
  231. 9B  DB E3     FINIT           initialize 87
  232.  w  DF /2     FIST mem2i      mem2i := 0
  233.  w  DB /2     FIST mem4i      mem4i := 0
  234.  w  DF /3     FISTP mem2i     mem2i := 0, pop
  235.  w  DB /3     FISTP mem4i     mem4i := 0, pop
  236.  w  DF /7     FISTP mem8i     mem8i := 0, pop
  237.  w  DE /4     FISUB mem2i     0 := 0 - mem2i
  238.  w  DA /4     FISUB mem4i     0 := 0 - mem4i
  239.  w  DE /5     FISUBR mem2i    0 := mem2i - 0
  240.  w  DA /5     FISUBR mem4i    0 := mem4i - 0
  241.  w  D9 C0+i   FLD i           push, 0 := old i
  242.  w  DB /5     FLD mem10r      push, 0 := mem10r
  243.  w  D9 /0     FLD mem4r       push, 0 := mem4r
  244.  w  DD /0     FLD mem8r       push, 0 := mem8r
  245.  w  D9 E8     FLD1            push, 0 := 1.0
  246.  w  D9 /5     FLDCW mem2i     control word := mem2i
  247.  w  D9 /4     FLDENV mem14    environment := mem14
  248.  w  D9 EA     FLDL2E          push, 0 := log base 2.0 of e
  249.  w  D9 E9     FLDL2T          push, 0 := log base 2.0 of 10.0
  250.  w  D9 EC     FLDLG2          push, 0 := log base 10.0 of 2.0
  251.  w  D9 ED     FLDLN2          push, 0 := log base e of 2.0
  252.  w  D9 EB     FLDPI           push, 0 := Pi
  253.  w  D9 EE     FLDZ            push, 0 := +0.0
  254.  w  DE C9     FMUL            1 := 1 * 0, pop
  255.  w  D8 C8+i   FMUL i          0 := 0 * i
  256.  w  DC C8+i   FMUL i,0        i := i * 0
  257.  w  D8 C8+i   FMUL 0,i        0 := 0 * i
  258.  w  D8 /1     FMUL mem4r      0 := 0 * mem4r
  259.  w  DC /1     FMUL mem8r      0 := 0 * mem8r
  260.  w  DE C8+i   FMULP i,0       i := i * 0, pop
  261.     DB E2     FNCLEX          nowait clear exceptions
  262.     DB E1     FNDISI          disable interrupts (.287 ignore)
  263.     DB E0     FNENI           enable interrupts (.287 ignore)
  264.     DB E3     FNINIT          nowait initialize 87
  265.  w  D9 D0     FNOP            no operation
  266.     DD /6     FNSAVE mem94    mem94 := 87 state
  267.     D9 /7     FNSTCW mem2i    mem2i := control word
  268.     D9 /6     FNSTENV mem14   mem14 := environment
  269.     DF E0     FNSTSW AX       AX := status word
  270.     DD /7     FNSTSW mem2i    mem2i := status word
  271.  w  D9 F3     FPATAN          0 := arctan(1/0), pop
  272.  w  D9 F8     FPREM           0 := REPEAT(0 - 1)
  273.  w  D9 F5     FPREM1          387 only: 0 := REPEAT(0 - 1) IEEE compat.
  274.  w  D9 F2     FPTAN           push, 1/0 := tan(old 0)
  275.  w  D9 FC     FRNDINT         0 := round(0)
  276.  w  DD /4     FRSTOR mem94    87 state := mem94
  277.  w  DD /6     FSAVE mem94     mem94 := 87 state
  278.  w  D9 FD     FSCALE          0 := 0 * 2.0 ** 1
  279. 9B  DB E4     FSETPM          set protection mode
  280.  w  D9 FE     FSIN            387 only: push, 1/0 := sine(old 0)
  281.  w  D9 FB     FSINCOS         387 only: push, 1 := sine, 0 := cos(old 0)
  282.  w  D9 FA     FSQRT           0 := square root of 0
  283.  w  DD D0+i   FST i           i := 0
  284.  w  D9 /2     FST mem4r       mem4r := 0
  285.  w  DD /2     FST mem8r       mem8r := 0
  286.  w  D9 /7     FSTCW mem2i     mem2i := control word
  287.  w  D9 /6     FSTENV mem14    mem14 := environment
  288.  w  DD D8+i   FSTP i          i := 0, pop
  289.  w  DB /7     FSTP mem10r     mem10r := 0, pop
  290.  w  D9 /3     FSTP mem4r      mem4r := 0, pop
  291.  w  DD /3     FSTP mem8r      mem8r := 0, pop
  292.  w  DF E0     FSTSW AX        AX := status word
  293.  w  DD /7     FSTSW mem2i     mem2i := status word
  294.  w  DE E9     FSUB            1 := 1 - 0, pop
  295.  w  D8 E0+i   FSUB i          0 := 0 - i
  296.  w  DC E8+i   FSUB i,0        i := i - 0
  297.  w  D8 E0+i   FSUB 0,i        0 := 0 - i
  298.  w  D8 /4     FSUB mem4r      0 := 0 - mem4r
  299.  w  DC /4     FSUB mem8r      0 := 0 - mem8r
  300.  w  DE E8+i   FSUBP i,0       i := i - 0, pop
  301.  w  DE E1     FSUBR           1 := 0 - 1, pop
  302.  w  D8 E8+i   FSUBR i         0 := i - 0
  303.  w  DC E0+i   FSUBR i,0       i := 0 - i
  304.  w  D8 E8+i   FSUBR 0,i       0 := i - 0
  305.  w  D8 /5     FSUBR mem4r     0 := mem4r - 0
  306.  w  DC /5     FSUBR mem8r     0 := mem8r - 0
  307.  w  DE E0+i   FSUBRP i,0      i := 0 - i, pop
  308.  w  D9 E4     FTST            compare 0 - 0.0
  309.  w  DD E0+i   FUCOM i         387 only: unordered compare 0 - i
  310.  w  DD E1     FUCOM           387 only: unordered compare 0 - 1
  311.  w  DD E8+i   FUCOMP i        387 only: unordered compare 0 - i, pop
  312.  w  DD E9     FUCOMP          387 only: unordered compare 0 - 1, pop
  313.  w  DA E9     FUCOMPP         387 only: unordered compare 0 - 1, pop both
  314. 9B            FWAIT           wait for 87 ready
  315.  w  D9 E5     FXAM            C3 -- C0 := type of 0
  316.  w  D9 C9     FXCH            exchange 0 and 1
  317.  w  D9 C8+i   FXCH 0,i        exchange 0 and i
  318.  w  D9 C8+i   FXCH i          exchange 0 and i
  319.  w  D9 C8+i   FXCH i,0        exchange 0 and i
  320.  w  D9 F4     FXTRACT         push, 1 := expo, 0 := sig
  321.  w  D9 F1     FYL2X           0 := 1 * log base 2.0 of 0, pop
  322.  w  D9 F9     FYL2XP1         0 := 1 * log base 2.0 of (0+1.0), pop
  323.